﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;

namespace Codeplex.Unity.AutoRegister.Config
{
    /// <summary>
    /// UnityContainerに登録するための情報
    /// </summary>
    public class RegistTypeTrait
    {
        private static InjectionMember[] EmptyInjectionMemberArray = new InjectionMember[0];

        private Type fromType;
        private Type lifetimeManager;
        private Type injectionMemberProvider;

        /// <summary>
        /// コンテナに登録する型を指定してインスタンスを初期化
        /// </summary>
        /// <param name="toType">コンテナに登録する型</param>
        public RegistTypeTrait(Type toType)
        {
            this.ToType = toType;
            this.InjectionMembers = EmptyInjectionMemberArray;
        }

        /// <summary>
        /// コンテナに登録する名前
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// コンテナから取り出される時に使用する型
        /// </summary>
        public Type FromType
        {
            get
            {
                return this.fromType ?? this.ToType;
            }

            set
            {
                if (!value.IsAssignableFrom(this.ToType))
                {
                    throw new ArgumentException(string.Format("{0} is not assinable from {1}", value.Name, this.ToType.Name));
                }

                this.fromType = value;
            }
        }

        /// <summary>
        /// コンテナに登録する型
        /// </summary>
        public Type ToType { get; private set; }
        
        /// <summary>
        /// コンテナからInjectionされるメンバーの情報
        /// </summary>
        public InjectionMember[] InjectionMembers { get; set; }

        /// <summary>
        /// 登録した型のインスタンスのライフタイムを管理する型
        /// </summary>
        public Type LifetimeManager 
        {
            get
            {
                return this.lifetimeManager ?? typeof(PerResolveLifetimeManager);
            }

            set
            {
                if (!typeof(LifetimeManager).IsAssignableFrom(value))
                {
                    throw new ArgumentException("value is not assinable LifetimeManager");
                }

                this.lifetimeManager = value;
            }
        }

        /// <summary>
        /// InjectionMemberを提供する型を指定する。
        /// </summary>
        public Type InjectionMemberProvider
        {
            get
            {
                return this.injectionMemberProvider ?? typeof(EmptyInjectionMemberProvider);
            }

            set
            {
                if (!typeof(InjectionMemberProvider).IsAssignableFrom(value))
                {
                    throw new ArgumentException("value is not assinable InjectionMemberProvider");
                }

                this.injectionMemberProvider = value;
            }
        }
    }
}
